%include "boot.inc"                       ; nasm编译时 -I 参数中包含了include路径，直接写文件名就可以

[ORG MBR_BASE_ADDR]

[SECTION .text]
[BITS 16]
global _start
_start:
    mov ax, 3                             ; 设置屏幕模式为文本模式，清除屏幕
    int 0x10

    mov ax, 0
    mov ss, ax
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    mov eax, 1                            ; 起始扇区号，我用的硬盘寻址是LBA，扇区编号从0开始，所以第二快扇区编号为1,若为CHS寻址则为2
    mov bx, LOADER_BASE_ADDR
    mov cx, 2
    call read_disk_lba

    mov si, load_loader_successfully
    call print

    jmp LOADER_BASE_ADDR                  ; 可以直接跳，虽然loader的前面添加了.gdt段，但是nasm编译时会自动把.text段放在最前面，所以0xD00处还是代码段的第一行代码

; --------------------------------------------------------
; 读硬盘
; eax 起始扇区号
; bx  将数据写入的内存地址
; cx  要读取的扇区数量，实际只用到cl
read_disk_lba:
    mov esi, eax                          ; 备份eax、cx
    mov di, cx

    mov dx, 0x1F2                         ; 0x1F2 8bit 指定读取或写入的扇区数
    mov al, cl
    out dx, al

    mov eax, esi
    mov dx, 0x1F3                         ; 0x1F3 8bit iba地址的前八位 0-7
    out dx, al

    mov cl, 8
    shr eax, cl
    mov dx, 0x1F4                         ; 0x1F4 8bit iba地址的中八位 8-15
    out dx, al

    shr eax, cl
    mov dx, 0x1F5                         ; 0x1F5 8bit iba地址的高八位 16-23
    out dx, al

    shr eax, cl
    mov dx, 0x1F6                         ; 0x1F6 低4位 0-3位iba地址的24-27，
    and al, 0b0000_1111                   ; 所以先将高4位置0，低4位保持不变
    or al, 0b1110_0000                    ; 再将高4位置为1110，
                                          ; 4 0表示主盘 1表示从盘，bochsrc中配置ata0-master代表Primary通道的主盘
                                          ; 5、7位固定为1
                                          ; 6 0表示CHS模式，1表示LAB模式，这里用的LBA模式
                                          ; 所以高4位为1110
    out dx, al

    mov dx, 0x1F7                         ; 0x1F7 8bit 命令或状态端口
    mov al, 0x20                          ; 0x20 读命令，0x30 写命令
    out dx, al

    mov cx, di                            ; di保存了要读取的扇区数
.loop:
    mov si, cx                            ; 双重循环，暂存cx
.no_ready:
    mov dx, 0x1F7                         ; 同一端口，还是0x1F7
    in al, dx
    and al, 0b10001000                    ; 只看第3位和第7位，
                                          ; 第3位为1表示硬盘控制器已准备好数据传输 0表示未准备好
                                          ; 第7位为1表示硬盘忙 0表示硬盘不忙
    cmp al, 0b00001000                    ; and之后期望为 0b0001000
    jnz .no_ready

    mov cx, 256                           ; 一个扇区512个字节，每次读一个字，所以循环256次
    mov dx, 0x1F0
.read_data:
    in ax, dx
    mov [bx], ax
    add bx, 2
    loop .read_data

    mov cx, si                            ; 恢复cx
    loop .loop
    ret

; --------------------------------------------------------
; 打印字符串
; si 传入字符串起始地址
print:
    mov ah, 0x0e
    mov bh, 0
    mov bl, 0x01
.loop:
    mov al, [si]
    cmp al, 0
    jz .done
    int 0x10

    inc si
    jmp .loop
.done:
    ret

load_loader_successfully:
    db "Load loader successfully...", 10, 13, 0

times 510 - ($ - $$) db 0
db 0x55, 0xaa